//
//  LXNetworkApi.swift
//  LXMoyaHelper
//
//  Created by yoctech on 2021/8/4.
//

import Foundation
import Moya

open class LXNet: TargetType, LXNetShowLoading {
    /// 请求域名
    open private(set) var baseURL: URL
    /// 请求域名后面的路径
    open private(set) var path: String = ""
    /// 请求方式
    open private(set) var method: Moya.Method = .get
    /// 测试数据
    open var sampleData: Data = Data()
    /// 任务创建,传参在这里
    open private(set) var task: Task = .requestPlain
    /// 请求头
    open private(set) var headers: [String : String]?
    
    open private(set) var isShowLoading: Bool = false
    
    open private(set) var isAutoHandError: Bool = true

    open private(set) var request: Cancellable?

    /// 必须参数初始化
    public init(baseURL: URL, path: String, method: Moya.Method, task: Task, headers: [String : String]?) {
        self.baseURL = baseURL
        self.path = path
        self.method = method
        self.task = task
        self.headers = headers
    }
    
    //MARK:- 链式语法
    
    
    /// 进度回调
    open var progress: ProgressBlock?
    
    /// 完成回调
    open var completion: Completion = { _ in }
    
    /// 自定义Moya.Result转换成需要类型的转换器,如果不赋值,就默认使用全局转换器
    open var serializeHandle: LXMoyaResultSerializer?

    //配合链式语法赋值
    
    
    /// 链式语法 - 初始化,可以带自己的域名
    public init(baseUrl:String? = nil) {
        guard let url = URL(string: baseUrl ?? LXNetManager.config.baseUrl) else {
            fatalError("请求域名配置不正确")
        }
        self.baseURL = url
    }
    /// 链式语法 - 请求路径
    open func path(_ path: String) -> Self {
        self.path = path
        return self
    }
    
    /// 链式语法 - HTTPMethod赋值,默认GET
    open func method(_ method: Moya.Method) -> Self {
        self.method = method
        return self
    }
    
    /// 链式语法 - 是否显示转圈动画
    open func showLoading(_ isShowLoading: Bool) -> Self {
        self.isShowLoading = isShowLoading
        return self
    }
    
    /// 链式语法 - 是否使用全局错误处理器, 默认是
    open func autoHandError(_ isAutoHandError: Bool) -> Self {
        self.isAutoHandError = isAutoHandError
        return self
    }


    /// 链式语法 - 请求任务
    open func task(_ task: Task) -> Self {
        self.task = task
        return self
    }
    /// 链式语法 - 请求头
    open func headers(_ headers: [String : String]) -> Self {
        self.headers = headers
        return self
    }
    /// 链式语法 - 进度回调
    open func progress(_ progress: @escaping ProgressBlock) -> Self {
        self.progress = progress
        return self
    }
    /// 链式语法 - 请求原生的完成回调,不使用任何转换器或者错误处理器
    open func completion(_ completion: @escaping Completion) -> Self {
        self.completion = completion
        return self
    }
    
    // 请求完成后对数据进行处理
    
    /// 链式语法 - 请求结果数据转换器
    open func serializeHandle(_ serializeHandle: LXMoyaResultSerializer) -> Self {
        self.serializeHandle = serializeHandle
        return self
    }

    /// 链式语法 - 请求完成回调-数据处理后
    open func completion<T:LXJsonMapper>(_ type: T.Type, success: @escaping (T)->Void, failure:((LXError)->Void)? = nil) -> Self {
        let serializeHandle = serializeHandle ?? LXNetManager.config.serializeHandle
        self.completion = { [weak self] result in
            let newResult: Result<T, LXError> = serializeHandle.serialize(result: result)
            switch newResult {
            case .success(let model):
                success(model)
            case .failure(let err):
                if self?.isAutoHandError ?? true {
                    LXNetManager.config.requestErrorHandler?.handleError(err, with: result)
                }
                failure?(err)
            }
        }
        return self
    }
    
    /// 链式语法 - 请求完成回调-数据处理后-数组
    open func completionArray<T:LXJsonMapper>(_ type: T.Type, success: @escaping ([T])->Void, failure:((LXError)->Void)? = nil) -> Self {
        let serializeHandle = serializeHandle ?? LXNetManager.config.serializeHandle
        self.completion = { [weak self] result in
            let newResult: Result<[T], LXError> = serializeHandle.serializeArray(result: result)
            switch newResult {
            case .success(let models):
                success(models)
            case .failure(let err):
                if self?.isAutoHandError ?? true {
                    LXNetManager.config.requestErrorHandler?.handleError(err, with: result)
                }
                failure?(err)
            }
        }
        return self
    }
    
    /// 链式语法 - 发起请求
    open func start() {
        request = LXNetManager.config.provider.request(.target(self), progress: progress, completion: completion)
    }
    
    /// 取消请求
    open func cancel() {
        request?.cancel()
    }
}


